// RtpToPcap.cpp : 定义 DLL 的导出函数。
//

#ifdef _WINDOWS
#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容
#define _CRT_SECURE_NO_WARNINGS
// Windows 头文件
#include <windows.h>
//#include <winsock2.h>
#else
//#include <arpa/inet.h>
#endif
#include "RtoToPcapImpl.h"
#include <chrono>
#include <string.h>

/*短整型高低字节交换
16位
15141312111098 76543210
将高位15141312111098移动8位到原先76543210的位置上
*/
#define Swap16(A) (( ((uint16_t)(A) & 0xff00) >> 8 ) |  ( ((uint16_t)(A) & 0x00ff) << 8 ) )

/*长整型高低字节交换
32位
*/
#define Swap32(A) ( (((uint32_t)(A) & 0xff000000) >> 24 ) | \
                    (((uint32_t)(A) & 0x00ff0000) >> 8 )  | \
                    (((uint32_t)(A) & 0x0000ff00) << 8 )  | \
                    (((uint32_t)(A) & 0x000000ff) << 24 ) )

RtpToPcap* RtpToPcap::create()
{
    return new RtoToPcapImpl();
}

void RtpToPcap::destroy(RtpToPcap* pPcap)
{
    delete pPcap;
    return;
}


RtoToPcapImpl::~RtoToPcapImpl()
{
    (void)close();
}

int32_t RtoToPcapImpl::open(const char* filename)
{
    int32_t ret = -1;

    do 
    {
        if (m_fp)
        {
            break;
        }
        m_fp = fopen(filename, "wb");
        if (!m_fp)
        {
            break;
        }
        PcapFileHeader header;
        int res = fwrite(&header, sizeof(header), 1, m_fp);
        if (res != 1)
        {
            break;
        }
        ret = 0;
    } while (0);

    if (ret && m_fp)
    {
        fclose(m_fp);
        m_fp = nullptr;
    }

    return ret;
}

void RtoToPcapImpl::writeRtpPacket(const uint8_t* pData, uint32_t bytes,
    uint32_t srcIp, uint16_t srcPort, uint32_t dstIp, uint16_t dstPort,
    uint32_t tv_sec, uint32_t tv_usec)
{
    if (!pData || !bytes)
    {
        return;
    }

    if (tv_sec == 0 && tv_usec == 0)
    {
        auto now = std::chrono::system_clock::now();
        // 转换为纪元开始的微秒计数
        auto duration_us = std::chrono::duration_cast<std::chrono::microseconds>(
            now.time_since_epoch()
            );

        // 提取秒和微秒
        const uint32_t us = 1000000;
        tv_sec = std::chrono::duration_cast<std::chrono::seconds>(duration_us).count();
        tv_usec = duration_us.count() % us;
    }

    // ===== 1. 构造伪头部 =====
    // 以太网帧头（MAC地址填充为0）
    uint8_t ethHeader[14] = { 0 };
    ethHeader[12] = 0x08; // IPv4类型 0x0800
    ethHeader[13] = 0x00;

    // IP头
    uint8_t ipHeader[20] = {
        0x45, 0x00, // 版本+头部长度
        0x00, 0x00, // 总长度（稍后计算）
        0x00, 0x00, 0x40, 0x00, // ID + 标志
        0x40, 0x11, // TTL(64) + 协议(UDP=17)
        0x00, 0x00, // 校验和（暂为0）
    };

    *reinterpret_cast<uint32_t*>(ipHeader + 12) = Swap32(srcIp); // 源IP
    *reinterpret_cast<uint32_t*>(ipHeader + 16) = Swap32(dstIp); // 目的IP



    // UDP头
    uint8_t udpHeader[8] = { 0 };

    *reinterpret_cast<uint16_t*>(udpHeader) = Swap16(srcPort); // 源端口

    *reinterpret_cast<uint16_t*>(udpHeader + 2) = Swap16(dstPort); // 目的端口
    uint16_t udpLength = sizeof(udpHeader) + bytes;

    *reinterpret_cast<uint16_t*>(udpHeader + 4) = Swap16(udpLength); // UDP长度

    // ===== 2. 计算各段长度 =====
    uint16_t ipTotalLength = sizeof(ipHeader) + sizeof(udpHeader) + bytes;

    *reinterpret_cast<uint16_t*>(ipHeader + 2) = Swap16(ipTotalLength);

    // ===== 3. 组装完整数据包 =====
    uint32_t fullPacketSize = sizeof(ethHeader) + ipTotalLength;
    if (m_fullPacket.size() != fullPacketSize)
    {
        m_fullPacket.resize(fullPacketSize);
    }
    uint8_t* ptr = m_fullPacket.data();

    memcpy(ptr, ethHeader, sizeof(ethHeader)); ptr += sizeof(ethHeader);
    memcpy(ptr, ipHeader, sizeof(ipHeader)); ptr += sizeof(ipHeader);
    memcpy(ptr, udpHeader, sizeof(udpHeader)); ptr += sizeof(udpHeader);
    memcpy(ptr, pData, bytes);

    // ===== 4. 写入PCAP记录头 =====
    PcapPacketHeader pcapHeader;
    pcapHeader.ts_sec = tv_sec;// Swap32(tv_sec);
    pcapHeader.ts_usec = tv_usec;// Swap32(tv_usec);
    pcapHeader.incl_len = fullPacketSize;// Swap32(fullPacketSize);
    pcapHeader.orig_len = fullPacketSize;// Swap32(fullPacketSize);

    fwrite(&pcapHeader, 1, sizeof(pcapHeader), m_fp);
    fwrite(m_fullPacket.data(), 1, fullPacketSize, m_fp);

    return;
}

int32_t RtoToPcapImpl::close()
{
    int32_t ret = -1;

    do 
    {
        if (m_fp)
        {
            fclose(m_fp);
            m_fp = nullptr;
        }

        ret = 0;
    } while (0);

    return ret;
}

// 这是已导出类的构造函数。



